<?php
/**
 * 	Bushido
 *
 * @category   Bushido
 * @package    Bushido_Db
 * @copyright  Copyright (c) 2008-2009 Nathan Keyes
 * @author Nathan Keyes
 * @version    $Id: Form.php 7 2009-11-14 22:42:08Z nkeyes $
 */

/**
 * 
 * @author Nathan Keyes
 *
 */
class Bushido_Form extends Zend_Dojo_Form
{	
	protected static $_fieldInputMap = array
	(
		//numeric types
		'TINYINT' => array
		(
			'inputType' => 'CheckBox',
			'validators' => array
			(
				array
				(
					'validator' => 'digits',
					'breakChainOnFailure' => true
				)
			)
		),
		'SMALLINT' => array
		(
			'inputType' => 'NumberSpinner',
			'validators' => array
			(
				array
				(
					'validator' => 'digits',
					'breakChainOnFailure' => true
				)
			)
		),
		'MEDIUMINT' => array
		(
			'inputType' => 'NumberSpinner',
			'validators' => array
			(
				array
				(
					'validator' => 'digits',
					'breakChainOnFailure' => true
				)
			)
		),
		'INT' => array
		(
			'inputType' => 'NumberSpinner',
			'validators' => array
			(
				array
				(
					'validator' => 'digits',
					'breakChainOnFailure' => true
				)
			)
		),
		'INTEGER' => array
		(
			'inputType' => 'NumberSpinner',
			'validators' => array
			(
				array
				(
					'validator' => 'digits',
					'breakChainOnFailure' => true
				)
			)
		),
		'BIGINT' => array
		(
			'inputType' => 'NumberSpinner',
			'validators' => array
			(
				array
				(
					'validator' => 'digits',
					'breakChainOnFailure' => true
				)
			)
		),
		'FLOAT' => array
		(
			'inputType' => 'NumberTextBox',
			'validators' => array
			(
				array
				(
					'validator' => 'float',
					'breakChainOnFailure' => true
				)
			)
		),
		'DOUBLE' => array
		(
			'inputType' => 'NumberTextBox',
			'validators' => array
			(
				array
				(
					'validator' => 'float',
					'breakChainOnFailure' => true
				)
			)
		),
		'REAL' => array
		(
			'inputType' => 'NumberTextBox',
			'validators' => array
			(
				array
				(
					'validator' => 'float',
					'breakChainOnFailure' => true
				)
			)
		),
		'DECIMAL' => array
		(
			'inputType' => 'NumberTextBox',
			'validators' => array
			(
				array
				(
					'validator' => 'float',
					'breakChainOnFailure' => true
				)
			)
		),
		'BIT' => array
		(
			'inputType' => 'NumberTextBox',
			'validators' => array
			(
				array
				(
					'validator' => 'digits',
					'breakChainOnFailure' => true
				)
			)
		),
		
		//date / time types
		'DATE' => array
		(
			'inputType' => 'DateTextBox',
			'validators' => array
			(
				array
				(
					'validator' => 'date',
					'breakChainOnFailure' => true,
					'options' => array
					(
						'format' => 'YYYY-MM-dd'
					)
				)
			)
		),
		'TIME' => array
		(
			'inputType' => 'TimeTextBox',
			'validators' => array
			(
				array
				(
					'validator' => 'regex',
					'breakChainOnFailure' => true,
					'options' => array
					(
						'pattern' => '\d\d:\d\d'
					)
				)
			)
		),
		'DATETIME' => array
		(
			'inputType' => 'hidden',
			'componentInputs' => array
			(
				array
				(
					'inputSuffix' => '_date',
					'inputType' => 'DateTextBox',
					'options' => array
					(
						'required' => true,
						'invalidMessage' => 'Invalid date specified.',
						//'datePattern'   => 'yyyy-MM-dd'
					),
					'validators' => array
					(
						array
						(
							'validator' => 'date',
							'breakChainOnFailure' => true,
							'options' => array
							(
								'format' => 'YYYY-MM-dd'
							)
						)
					)
				),
				array
				(
					'inputSuffix' => '_time',
					'inputType' => 'TimeTextBox',
					'options' => array
					(
						'required' => true,
						'invalidMessage' => 'Invalid time specified.',
						//'datePattern'   => 'hh:mm'
					),
					'validators' => array
					(
						array
						(
							'validator' => 'regex',
							'breakChainOnFailure' => true,
							'options' => array
							(
								'pattern' => '\d\d:\d\d'
							)
						)
					)
				)
			)
		),
		'TIMESTAMP' => array
		(
			'inputType' => 'Hidden',
			'componentInputs' => array
			(
				array
				(
					'inputSuffix' => '_date',
					'inputType' => 'DateTextBox',
					'options' => array
					(
						'required' => true,
						'invalidMessage' => 'Invalid date specified.',
						//'datePattern'   => 'yyyy-MM-dd'
					),
					'validators' => array
					(
						array
						(
							'validator' => 'date',
							'breakChainOnFailure' => true,
							'options' => array
							(
								'format' => 'YYYY-MM-dd'
							)
						)
					)
				),
				array
				(
					'inputSuffix' => '_time',
					'inputType' => 'TimeTextBox',
					'options' => array
					(
						'required' => true,
						'invalidMessage' => 'Invalid time specified.',
						//'datePattern'   => 'hh:mm'
					),
					'validators' => array
					(
						array
						(
							'validator' => 'regex',
							'breakChainOnFailure' => true,
							'options' => array
							(
								'pattern' => '\d\d:\d\d'
							)
						)
					)
				)
			)
		),
		'YEAR' => array
		(
			'inputType' => 'DateTextBox',
			'validators' => array
			(
				array
				(
					'validator' => 'date',
					'breakChainOnFailure' => true,
					'options' => array
					(
						'format' => 'YYYY-MM-dd'
					)
				)
			)
		),
		
		// string types
		'CHAR' => array
		(
			'inputType' => 'ValidationTextBox',
			'filters' => array
			(
				'filter' => 'StripTags'
			),
			'validators' => array
			(
				array
				(
					'validator' => 'StringLength',
					'breakChainOnFailure' => true,
					'options' => array
					(
						'min' => 1,
						'max' => 255
					)
				)
			)
		),
		'VARCHAR' => array
		(
			'inputType' => 'ValidationTextBox',
			'filters' => array
			(
				'filter' => 'StripTags'
			),
			'validators' => array
			(
				array
				(
					'validator' => 'StringLength',
					'breakChainOnFailure' => true,
					'options' => array
					(
						'min' => 1,
						'max' => 255
					)
				)
			)
		),
		'TINYTEXT' => array
		(
			'inputType' => 'SimpleTextarea',
			'filters' => array
			(
				'filter' => 'StripTags'
			),
		),
		'TEXT' => array
		(
			'inputType' => 'SimpleTextarea',
			'filters' => array
			(
				'filter' => 'StripTags'
			),
		),
		'MEDIUMTEXT' => array
		(
			'inputType' => 'SimpleTextarea',
			'filters' => array
			(
				'filter' => 'StripTags'
			),
		),
		'LONGTEXT' => array
		(
			'inputType' => 'SimpleTextarea',
			'filters' => array
			(
				'filter' => 'StripTags'
			),
		),
		'ENUM' => array
		(
			'inputType' => 'FilteringSelect'
		),
		'SET' => array
		(
			'inputType' => 'FilteringSelect'
		),
		
		//binary types
		'TINYBLOB' => array
		(
			'inputType' => 'File',
			'validators' => array
			(
				array
				(
					'Extension', false, 'pdf,doc,docx,xls,xlsx,ppt,pptx,tiff,jpg,jpeg,gif,bmp,txt,rtf'
				)
			)
		),
		'BLOB' => array
		(
			'inputType' => 'File',
			'validators' => array
			(
				array
				(
					'Extension', false, 'pdf,doc,docx,xls,xlsx,ppt,pptx,tiff,jpg,jpeg,gif,bmp,txt,rtf'
				)
			)
		),
		'MEDIUMBLOB' => array
		(
			'inputType' => 'File',
			'validators' => array
			(
				array
				(
					'Extension', false, 'pdf,doc,docx,xls,xlsx,ppt,pptx,tiff,jpg,jpeg,gif,bmp,txt,rtf'
				)
			)
		),
		'LONGBLOB' => array
		(
			'inputType' => 'File',
			'validators' => array
			(
				array
				(
					'Extension', false, 'pdf,doc,docx,xls,xlsx,ppt,pptx,tiff,jpg,jpeg,gif,bmp,txt,rtf'
				)
			)
		),
	);
	
	
	public function getFieldInputMap()
	{
		return $this->_fieldInputMap;
	}
	
	/**
	 * 
	 * @return Bushido_Db_Table_Row
	 */
	
	public function generateElement($field, $fieldData)
	{
		if((empty($fieldData['PRIMARY']) && empty($fieldData['IDENTITY'])) || !$this->_sequence)
		{
			$fieldOptions = array('label' => $field);
			$fieldValue = null;
			
			$fieldType = isset($fieldData['DATA_TYPE']) && isset(self::$_fieldInputMap[strtoupper($fieldData['DATA_TYPE'])]) ? self::$_fieldInputMap[strtoupper($fieldData['DATA_TYPE'])]['inputType'] : 'ValidationTextBox';
			
			if(isset($fieldData['fieldDetails']) && is_array($fieldData['fieldDetails']))
			{
				$fieldType = isset($fieldData['fieldDetails']['type']) ? $fieldData['fieldDetails']['type'] : $fieldType;
				if($fieldType == 'generated')
				{
					return;
				}
				if($fieldType == 'subForm')
				{
					return;
				}
				$fieldOptions = isset($fieldData['fieldDetails']['options']) ? $fieldData['fieldDetails']['options'] : $fieldOptions;
				$fieldValue = isset($fieldData['fieldDetails']['defaultValue']) ? $fieldData['fieldDetails']['defaultValue'] : $fieldValue;
				
			}
			
			if(!empty(self::$_fieldInputMap[strtoupper($fieldData['DATA_TYPE'])]['filters']))
			{
				$filters = self::$_fieldInputMap[strtoupper($fieldData['DATA_TYPE'])]['filters'];
				unset(self::$_fieldInputMap[strtoupper($fieldData['DATA_TYPE'])]['filters']);
			}
			
			if(!empty(self::$_fieldInputMap[strtoupper($fieldData['DATA_TYPE'])]['validators']))
			{
				$validators = self::$_fieldInputMap[strtoupper($fieldData['DATA_TYPE'])]['validators'];
				unset(self::$_fieldInputMap[strtoupper($fieldData['DATA_TYPE'])]['validators']);
			}
			$element = $this->createElement($fieldType, $field, $fieldOptions);
			
			if($filters)
			{
				$element->addFilters($filters);
				unset($filters);
			}
			
			if($validators)
			{
				$element->addValidators($validators);
				unset($validators);
			}
			$this->addElement($element);
			//$this->setdefault($field, $fieldValue);
			
			if(isset(self::$_fieldInputMap[strtoupper($fieldData['DATA_TYPE'])]['componentInputs']) && is_array(self::$_fieldInputMap[strtoupper($fieldData['DATA_TYPE'])]['componentInputs']))
			{
				foreach(self::$_fieldInputMap[strtoupper($fieldData['DATA_TYPE'])]['componentInputs'] as $componentInput)
				{
					$options = isset($componentInput['options']) && is_array($componentInput['options']) ? $componentInput['options'] : array();
					$this->addElement($this->createElement($componentInput['inputType'], $field . $componentInput['inputSuffix'], $options));
				}
				unset($componentInput);
			}
		}
	}
	

	/**
	 * (non-PHPdoc)
	 * @see library/Zend/Zend_Form#setDefault()
	 */
	
	public function setDefault($name, $value)
	{
		$name = (string) $name;
		if ($element = $this->getElement($name))
		{
			$element->setValue($value);
			//Zend_Debug::dump($name);
			//var_dump($this->getElement($name . '_date'));
						
			if($this->getElement($name . '_date') && $this->getElement($name . '_time'))
			{
				//Zend_Debug::dump($name, 'datetime:');
				$dateParts = split('\ +', $value, 2);
				//var_dump
				$this->getElement($name . '_date')->setValue($dateParts[0]);
				$this->getElement($name . '_time')->setValue('T'.$dateParts[1]);
			}
			elseif(preg_match('/_date$/i', $name) && $this->getElement(preg_replace('/_date$/i', '', $name)) && $this->getElement(preg_replace('/_date$/i', '_time', $name)))
			{
				//Zend_Debug::dump('date: ' . $name);
				$dateTimeElement = $this->getElement(preg_replace('/_date$/i', '', $name));
				$dateTimeElement->setValue($element->getValue() . $this->getElement(preg_replace('/_date$/i', '_time', $name))->getValue());
				
				//Zend_Debug::dump($dateTimeElement->getName() . ': ' . $dateTimeElement->getValue());
			}
			elseif(preg_match('/_time$/i', $name) && $this->getElement(preg_replace('/_time$/i', '', $name)) && $this->getElement(preg_replace('/_time$/i', '_date', $name)))
			{
				//Zend_Debug::dump('time: ' . $name);
				$dateTimeElement = $this->getElement(preg_replace('/_time$/i', '', $name));
				$dateTimeElement->setValue($this->getElement(preg_replace('/_time$/i', '_date', $name))->getValue() . $element->getValue());
				
				//Zend_Debug::dump($dateTimeElement->getName() . ': ' . $dateTimeElement->getValue());
			}
			else
			{	
				/*
				Zend_Debug::dump($this->getElement($name . '_date'));
				Zend_Debug::dump($this->getElement($name . '_time'));
				*/
			}
			
        }
        else
        {
        	if(is_scalar($value))
        	{
        		foreach ($this->getSubForms() as $subForm)
        		{
        			$subForm->setDefault($name, $value);
                }
                unset($subForm);
            }
            elseif(is_array($value) && ($subForm = $this->getSubForm($name)))
            {
            	$subForm->setDefaults($value);
            }
        }
        //Zend_Debug::dump($this->getValues(), 'values in setDefault:');
        return $this;
	}
	
	public function getValue($name)
	{
		//Zend_Debug::dump($name);
		if($this->getElement($name . '_date') && $this->getElement($name . '_time'))
		{
			//Zend_Debug::dump('datetime!');
			return $this->getElement($name . '_date')->getValue() . $this->getElement($name . '_time')->getValue();
		}
    	else
    	{
    		//Zend_Debug::dump('not datetime!');
    		return parent::getValue($name);
    	}
    }

	/**
	 * 
	 * @param $resetLabel
	 * @param $submitLabel
	 * @return unknown_type
	 */
	public function addResetSubmit($resetLabel, $submitLabel)
	{
		$this->setMethod('post');
		//$this->addElement('reset', $resetLabel);
		$this->addElement('Button', $submitLabel, array('label' => $submitLabel, 'value' => $submitLabel, 'type' => 'submit', 'dijitParams' => array('label' => $submitLabel, 'value' => $submitLabel)));
				
	}
	
	
	protected function _clearHiddenLabels(Zend_Form $form)
	{
		foreach($form->getSubForms() as $subForm)
		{
			$this->_clearHiddenLabels($subForm);
		}
		unset($subForm);
		
		foreach($form->getElements() as $element)
		{
			if(trim($element->getLabel()) == '')
			{
				$element->setLabel(null);
				$element->removeDecorator('Label');
			}
		}
		unset($element);
	}
	
	public function __toString()
	{
		$this->_clearHiddenLabels($this);
		return parent::__toString();
	}
	
	public function isValid($data)
    {
    	$this->populate($data);
    	return parent::isValid($data);
    }

}